﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;
using McTools.Xrm.Connection;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Metadata;
using RoleUpdater.DelegatesHelpers;
using RoleUpdater.Controls;

namespace RoleUpdater
{
    /// <summary>
    /// Application main form
    /// </summary>
    public sealed partial class MainForm : Form
    {
        #region Variables

        /// <summary>
        /// Crm organization service
        /// </summary>
        IOrganizationService _service;

        /// <summary>
        /// Connection manager
        /// </summary>
        readonly ConnectionManager _cManager;

        /// <summary>
        /// Control that holds list of connections
        /// </summary>
        readonly CrmConnectionStatusBar _ccsb;

        RoleManager _rManager;

        private int _currentStep = 1;

        /// <summary>
        /// List of all entities metadata
        /// </summary>
        List<EntityMetadata> _entities;

        private UpdateSettings _settings; 

        #endregion Variables

        #region Constructor

        /// <summary>
        /// Initializes a new instance of class MainForm
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            // Displays application version
            Text = string.Format("{0} (v{1})", Text, Assembly.GetExecutingAssembly().GetName().Version);

            // Prepare connection statusbar control
            _cManager = new ConnectionManager(this);
            _cManager.ConnectionSucceed += CManagerConnectionSucceed;
            _cManager.ConnectionFailed += CManagerConnectionFailed;
            _cManager.StepChanged += CManagerStepChanged;

            _ccsb = new CrmConnectionStatusBar(_cManager) {BackColor = Color.White};
            Controls.Add(_ccsb);

            _settings = new UpdateSettings();

            tTip.SetToolTip(pbBug, "Submit a bug request");
            tTip.SetToolTip(pbComment, "Start a discussion");
            tTip.SetToolTip(pbDonate, "Donate using PayPal");
            tTip.SetToolTip(pbRate, "Rate this tool");
            tTip.SetToolTip(pbNetwork, "Define a custom proxy");
        }

        #endregion Constructor

        #region Connection handlers

        void CManagerStepChanged(object sender, StepChangedEventArgs e)
        {
            LabelDelegates.SetColor(lblConnectionSteps, Color.Black);
            LabelDelegates.SetText(lblConnectionSteps, e.CurrentStep);
        }

        void CManagerConnectionFailed(object sender, ConnectionFailedEventArgs e)
        {
            LabelDelegates.SetColor(lblConnectionSteps, Color.Red);
            LabelDelegates.SetText(lblConnectionSteps, e.FailureReason);
            _service = null;
        }

        void CManagerConnectionSucceed(object sender, ConnectionSucceedEventArgs e)
        {
            _service = e.OrganizationService;

            _ccsb.SetConnectionStatus(true, e.ConnectionDetail);

            _rManager = new RoleManager(_service);

            LabelDelegates.SetText(lblConnectionSteps, "Loading privileges metadata...");
            _entities = MetadataHelper.GetEntitiesMetadata(_service, EntityFilters.Privileges);

            if (e.Parameter != null && e.Parameter.ToString() == "LoadRoles")
            {
                LoadRolesAndPrivileges();
            }
        }

        #endregion

        #region Methods

        private void LoadRolesAndPrivileges()
        {
            if (_service == null)
            {
                _cManager.AskForConnection("LoadRoles");
            }
            else
            {
                CommonDelegates.SetCursor(this, Cursors.WaitCursor);
                
                var bwFillRolesAndPrivileges = new BackgroundWorker();
                bwFillRolesAndPrivileges.DoWork += BwFillRolesAndPrivilegesDoWork;
                bwFillRolesAndPrivileges.RunWorkerCompleted += BwFillRolesAndPrivilegesRunWorkerCompleted;
                bwFillRolesAndPrivileges.RunWorkerAsync();
            }
        }

        private void BwFillRolesAndPrivilegesRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                var errorMessage = CrmExceptionHelper.GetErrorMessage(e.Error, true);
                
                LabelDelegates.SetColor(lblConnectionSteps, Color.Red);
                LabelDelegates.SetText(lblConnectionSteps, errorMessage);
            }
            else
            {
                LabelDelegates.SetColor(lblConnectionSteps, Color.Black);
                LabelDelegates.SetText(lblConnectionSteps, string.Empty);

                BtnNextClick(null, null);

                pnlConnection.Visible = false;
                pnlSteps.Visible = true;
                btnNext.Visible = true;
            }

            CommonDelegates.SetCursor(this, Cursors.Default);
        }

        private void BwFillRolesAndPrivilegesDoWork(object sender, DoWorkEventArgs e)
        {
            // Retrieve all roles without parent role
            LabelDelegates.SetText(lblConnectionSteps, "Loading roles ...");
            _rManager.LoadRootRoles();
           
            // Retrieve all privileges
            LabelDelegates.SetText(lblConnectionSteps, "Loading privileges...");
            _rManager.LoadPrivileges();

           LabelDelegates.SetText(lblConnectionSteps, string.Empty);
            CommonDelegates.SetCursor(this, Cursors.Default);
        }

        private void BtnConnectClick(object sender, EventArgs e)
        {
            if (_service == null)
            {
                _cManager.AskForConnection("LoadRoles");
            }
            else
            {
                CommonDelegates.SetCursor(this, Cursors.WaitCursor);

                var bwFillRolesAndPrivileges = new BackgroundWorker();
                bwFillRolesAndPrivileges.DoWork += BwFillRolesAndPrivilegesDoWork;
                bwFillRolesAndPrivileges.RunWorkerCompleted += BwFillRolesAndPrivilegesRunWorkerCompleted;
                bwFillRolesAndPrivileges.RunWorkerAsync();
            }
        }

        private void BtnNextClick(object sender, EventArgs e)
        {
            switch(_currentStep)
            {
                case 1:
                    {
                        pnlConnection.Visible = false;
                        pnlSteps.Visible = true;
                        btnPrevious.Visible = true;
                        btnReset.Visible = true;
                        btnNext.Visible = true;

                        // Adds the role selection control in main form
                        var ctrl = new RoleSelectionControl(_rManager.Roles, _settings);
                        pnlSteps.Controls.Add(ctrl);
                        _currentStep = 2;
                    }
                    break;
                case 2:
                    {
                        pnlConnection.Visible = false;
                        pnlSteps.Visible = true;
                        btnPrevious.Visible = true;
                        btnReset.Visible = true;

                        _settings.SelectedRoles = ((RoleSelectionControl) pnlSteps.Controls[0]).SelectedRoles;
                        pnlSteps.Controls.Clear();

                        var ctrl = new PrivilegeLevelSelectionControl(_rManager, _entities, _settings);
                        pnlSteps.Controls.Add(ctrl);
                        _currentStep = 3;
                    }
                    break;
                case 3:
                    {
                        pnlConnection.Visible = false;
                        pnlSteps.Visible = true;
                        btnNext.Enabled= false;
                        btnPrevious.Visible = true;
                        btnReset.Visible = true;

                        _settings.Actions = ((PrivilegeLevelSelectionControl)pnlSteps.Controls[0]).Actions;
                        pnlSteps.Controls.Clear();

                        var ctrl = new UpdateControl(_rManager, _settings);
                        pnlSteps.Controls.Add(ctrl);
                        _currentStep = 4;
                    }
                    break;
            }
        }

        private void BtnPreviousClick(object sender, EventArgs e)
        {
            switch (_currentStep)
            {
                case 2:
                    {
                        pnlConnection.Visible = true;
                        pnlSteps.Visible = false;
                        pnlSteps.Controls.Clear();
                        _currentStep = 1;

                        btnNext.Visible = false;
                        btnPrevious.Visible = false;
                        btnReset.Visible = false;
                    }
                    break;
                case 3:
                    {
                        pnlConnection.Visible = false;
                        pnlSteps.Visible = true;

                        btnNext.Visible = true;
                        btnPrevious.Visible = true;
                        btnReset.Visible = true;

                        // Adds the role selection control in main form
                        pnlSteps.Controls.Clear();
                        var ctrl = new RoleSelectionControl(_rManager.Roles, _settings);
                        pnlSteps.Controls.Add(ctrl);
                        _currentStep = 2;
                    }
                    break;
                case 4:
                    {
                        pnlConnection.Visible = false;
                        pnlSteps.Visible = true;

                        btnNext.Visible = true;
                        btnNext.Enabled = true;
                        btnPrevious.Visible = true;
                        btnReset.Visible = true;

                        pnlSteps.Controls.Clear();
                        var ctrl = new PrivilegeLevelSelectionControl(_rManager, _entities, _settings);
                        pnlSteps.Controls.Add(ctrl);
                        _currentStep = 3;
                    }
                    break;
            }
        }

        private void BtnResetClick(object sender, EventArgs e)
        {
            pnlSteps.Controls.Clear();
            _settings = new UpdateSettings();
            var ctrl = new RoleSelectionControl(_rManager.Roles, _settings);
            pnlSteps.Controls.Add(ctrl);
            btnNext.Enabled = true;

            _currentStep = 2;
        }

        private void PbRateClick(object sender, EventArgs e)
        {
            Process.Start("http://roleupdater.codeplex.com/releases");
        }

        private void PbBugClick(object sender, EventArgs e)
        {
             Process.Start("http://roleupdater.codeplex.com/WorkItem/Create");
        }

        private void PbCommentClick(object sender, EventArgs e)
        {
            Process.Start("http://roleupdater.codeplex.com/discussions");
        }

        private void PbDonateClick(object sender, EventArgs e)
        {
            var url =
               string.Format(
                   "https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business={0}&lc={1}&item_name={2}&currency_code={3}&bn=PP%2dDonationsBF",
                   "tanguy92@hotmail.com",
                   "FR",
                   "Donation%20for%20MSCRM%20Tools%20-%20Role%20Updater",
                   "EUR");

            Process.Start(url);
        }
    
        #endregion
    }
}